package ${package}.service.${classname}.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.imydao.safetystandard.basic.excel.ExcelUtils;
import com.imydao.safetystandard.basic.excel.res.ExcelRes;
import com.imydao.safetystandard.basic.page.res.PageBean;
import com.imydao.safetystandard.basic.res.BaseRes;
import com.imydao.safetystandard.basic.system.enums.BasicNewEnum;
import com.imydao.safetystandard.basic.system.enums.EntryMethodEnum;
import com.imydao.safetystandard.basic.system.enums.InputChannelEnum;
import ${package}.db.${classname}.mapper.${ClassName}Mapper;
import ${package}.db.${classname}.model.${ClassName};
import ${package}.dto.${classname}.excel.${ClassName}ExcelExportDto;
import ${package}.dto.${classname}.excel.${ClassName}ExcelImportDto;
import ${package}.dto.${classname}.req.${ClassName}AddDto;
import ${package}.dto.${classname}.req.${ClassName}EditDto;
import ${package}.dto.${classname}.req.${ClassName}ImportDto;
import ${package}.dto.${classname}.req.${ClassName}ListDto;
import ${package}.dto.${classname}.res.${ClassName}DetailRes;
import ${package}.service.${classname}.${ClassName}Service;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * ${tableComment}
 *
 * @author ${author} ${email}
 * @since ${version} ${date}
 */
@Slf4j
@Service
@AllArgsConstructor
public class ${ClassName}ServiceImpl extends ServiceImpl<${ClassName}Mapper, ${ClassName}> implements ${ClassName}Service {

    private final ${ClassName}Mapper ${className}Mapper;

    @Override
    public BaseRes<PageBean<${ClassName}>> pageList(${ClassName}ListDto dto) {
        dto.setOrderBy("id desc");
        dto.start();
        List<${ClassName}> list = ${className}Mapper.selectByWhere(dto);
        return BaseRes.getSuccess(PageBean.getPageBean(list));
    }

    @Override
    public BaseRes<Long> add(${ClassName}AddDto dto) {
        //1、构造实体对象
        ${ClassName} entity = new ${ClassName}();
        BeanUtil.copyProperties(dto, entity);
        //2、补全通用属性
        completeCommonProperties(dto, entity);
        //3、对象入库
        this.save(entity);
        return BaseRes.getSuccess(entity.getId());
    }

    @Override
    public BaseRes<Long> edit(${ClassName}EditDto dto) {
        //1、查询实体对象
        ${ClassName} entity = this.getById(dto.getId());
        if (entity == null) {
            return BaseRes.getError("object.not.exist");
        }
        //1.1、更新实体对象，忽略null值
        BeanUtil.copyProperties(dto, entity, CopyOptions.create().setIgnoreNullValue(true));
        //2、更新通用属性
        updateCommonProperties(dto, entity);
        //3、对象更新入库
        this.updateById(entity);
        return BaseRes.getSuccess(entity.getId());
    }

    @SneakyThrows(Exception.class)
    @Override
    public BaseRes<ExcelRes<${ClassName}ExcelImportDto>> importExcel(MultipartFile excel, ${ClassName}ImportDto dto) {
        //1、解析excel数据（如获取数据为空，请检查titleRows和headerRows配置是否正确）
        List<${ClassName}ExcelImportDto> importDataList = ExcelUtils
                .importExcel(excel, 1, 1, ${ClassName}ExcelImportDto.class);
        if (importDataList == null || importDataList.isEmpty()) {
            log.error("excel无内容");
            return BaseRes.getI18nError("basic.excel.no.content");
        }
        //2、过滤空行（指定字段为空或空白行）
        importDataList = importDataList.stream().filter(x -> !x.isEmpty()).collect(Collectors.toList());
        if (importDataList.isEmpty()) {
            log.error("excel校验为空白行，无正确内容");
            return BaseRes.getI18nError("basic.excel.no.content");
        }
        //3、数据校验
        String errMsg = validExcelData(importDataList);
        if (errMsg != null) {
            return BaseRes.getI18nError(errMsg);
        }
        //4、批量入库
        List<${ClassName}> persistentDateList = importDataList.stream().map(x -> {
            ${ClassName} item = new ${ClassName}();
            BeanUtil.copyProperties(x, item, CopyOptions.create().setIgnoreNullValue(true));
            //补全导入数据
            completeImportProperties(dto, item);
            return item;
        }).collect(Collectors.toList());
        this.saveBatch(persistentDateList, 500);
        //5、返回导入结果信息
        ExcelRes<${ClassName}ExcelImportDto> importResult = new ExcelRes<>();
        importResult.setTotal(importDataList.size());
        importResult.setInsertTotal(persistentDateList.size());
        importResult.setFailTotal(0);
        return BaseRes.getSuccess(importResult);
    }

    @Override
    public List<${ClassName}ExcelExportDto> exportExcel(${ClassName}ListDto dto) {
        List<${ClassName}ExcelExportDto> resultList = Collections.emptyList();
        //分页响应数据
        BaseRes<PageBean<${ClassName}>> pageList = this.pageList(dto);
        if (pageList.success()) {
            //分页数据
            PageBean<${ClassName}> listData = pageList.getData();
            //列表数据
            List<${ClassName}> list = listData.getList();
            //对象转换
            resultList = list.stream().map(x -> {
                ${ClassName}ExcelExportDto item = new ${ClassName}ExcelExportDto();
                BeanUtil.copyProperties(x, item, CopyOptions.create().setIgnoreNullValue(true));
                return item;
            }).collect(Collectors.toList());
        }
        return resultList;
    }

    @Override
    public BaseRes<${ClassName}DetailRes> detail(Long id) {
        //1、查询实体对象
        ${ClassName} ${className} = this.getById(id);
        if (${className} == null) {
            return BaseRes.getError("object.not.exist");
        }
        //2、构造返回对象
        ${ClassName}DetailRes result = new ${ClassName}DetailRes();
        BeanUtil.copyProperties(${className}, result);
        return BaseRes.getSuccess(result);
    }

    @Override
    public BaseRes<Long> delete(Long id) {
        //1、查询实体对象
        ${ClassName} entity = this.getById(id);
        if (entity == null) {
            return BaseRes.getError("object.not.exist");
        }
        //2、更新逻辑删除
        entity.setDeleted(BasicNewEnum.YES.getCode().byteValue());
        entity.setDeleteTime(LocalDateTime.now());
        this.updateById(entity);
        return BaseRes.getSuccess(id);
    }

    /**
     * 补全实体通用数据
     * @param dto 新增请求实体对象
     * @param entity 持久化实体对象
     */
    private void completeCommonProperties(${ClassName}AddDto dto, ${ClassName} entity) {
        this.completeCommonProperties(dto.getCustomerId(), dto.getLogInUserId(), entity);
    }

    /**
     * 补全excel导入实体数据
     * @param dto 客户id
     * @param entity 持久化实体对象
     */
    private void completeImportProperties(${ClassName}ImportDto dto, ${ClassName} entity) {
        //业务数据
        BeanUtil.copyProperties(dto, entity, CopyOptions.create().setIgnoreNullValue(true));
        entity.setInputChannel(InputChannelEnum.PC.getCode());
        //通用数据
        this.completeCommonProperties(dto.getCustomerId(), dto.getLogInUserId(), entity);
        entity.setEntryMethod(EntryMethodEnum.IMPORT.getCode());
    }

    /**
     * 补全实体通用数据
     * @param customerId 客户id
     * @param createUserId 创建人
     * @param entity 持久化实体对象
     */
    private void completeCommonProperties(Long customerId, Long createUserId, ${ClassName} entity) {
        entity.setId(IdWorker.getId());
        entity.setCustomerId(customerId);
        entity.setInputChannel((byte) 0);
        entity.setEntryMethod((byte) 0);
        entity.setCreateTime(LocalDateTime.now());
        entity.setCreateUserId(createUserId);
        entity.setUpdateTime(LocalDateTime.now());
        entity.setDeleted(BasicNewEnum.NO.getCode().byteValue());
    }

    /**
     * 更新实体变更更新时间等数据
     * @param dto 更新请求实体对象
     * @param entity 持久化实体对象
     */
    private void updateCommonProperties(${ClassName}EditDto dto, ${ClassName} entity) {
        entity.setUpdateTime(LocalDateTime.now());
        entity.setUpdateUserId(dto.getLogInUserId());
    }

    /**
     * excel 导入数据校验
     * @param importDataList 待导入数据
     * @return null标识校验通过，反之不通过，提示国际化信息
     */
    private String validExcelData(List<${ClassName}ExcelImportDto> importDataList) {
        //返回文字需要国际化！
        return null;
    }
}